<?php
/**
 * Created by PhpStorm.
 * User: admin
 * Date: 2019/1/15
 * Time: 23:05
 */
namespace app\common\library\task;



use app\common\model\Zbrateconfig;
use app\common\model\zbtask\Money;
use app\common\utils\Utils;
use think\Db;
use think\exception\ValidateException;

class BaseRateService
{

    protected static $new; //申请一个私有的静态成员变量来保存该类的唯一实例
    protected static $radio = 0.1;
    protected static $rateconfig = null;
    protected static $taskMoney = null;
    protected static $config = null;
    protected $data = null;
    protected $old = null;
    protected $sureRes= null;
    public function __construct() {
        self::$radio = config('site.money_tax_radio');
        self::$rateconfig = new Zbrateconfig();
        self::$taskMoney = new Money();
        if (!self::$config) {
            self::$config = $this->getConfig();
        }
    }


    public static function instance () { //声明一个静态公共方法，供外部获取唯一实例
        if (!(self::$new instanceof self)) {
            self::$new = new self;
        }

        return self::$new;
    }


    /**
     * 获取配置
     */
    public  function getConfig() {
        $list = self::$rateconfig->all(function($query){
            $query->order('tax_money', 'asc');
        }, '', true);
        foreach ($list as $k => &$v) {
            $v['money'] = Utils::explodeStr($v['money'], '-');
        }

        $list = collection($list)->toArray();
        return $list;
    }



    /**
     * 设置要处理的数
     * $data['money']
     * $data['user_id']
     * $data['money_type']
     */
    public function setData($data) {
        if (!isset($data['money']) || !isset($data['user_id']) || !isset($data['money_type'])) {
            throw new ValidateException('参数传递错误');
        }
        $this->data = $data;
        return $this;
    }
    /**
     * 获取历史众包费
     * 需要加入时间限制 时间限制为当前任务时间之前的已经发送的数据 进行众包费计算
     * @param int $time  当前税率时间   根据这个时间解析出 今年开始时间 税率：开始时间  ==》 当前$time时间
     * @return  object
     */
    public function getOld($time, $where = []) {
        if (!$this->data) {
            throw new ValidateException('请先设置数据');
        }
        $year = date('Y', $time);
        $start = mktime(0, 0, 0, 1, 1, $year);  //今年开始时间

        $old = self::$taskMoney
            ->where(['user_id'=> $this->data['user_id'], 'status'=> 1, 'type' => ['neq', 2]])
            ->where(['createtime'=> ['elt', $time]]) //大于等于，因为相等的时间戳可能同一个人，有好几条数据
            ->where(['createtime'=> ['gt', $start]])
            ->where($where)
            ->sum('money'); //总众包费用 有效 未驳回众包费 如果删除某一条众包费 会导致重新计算
        if(!$old) {
            $old = 0;
        }

        $this->old = $old;

        return $this;
    }

    //确定本次众包费纳税金额  1为应发 2为实发
    public function sureTax() {
        if ($this->old === null) {
            throw new ValidateException('请先计算历史众包费');
        }
        //获取当前数据所出的熟虑的税率
        $oldDetail = $this->detail();
        if ($this->data['money_type'] == 1) {
            $res = $this->taxMoney($oldDetail);
        } else {
            $res = $this->taxRealMoney($oldDetail);
        }
        if (!$res) {
            throw new ValidateException('运算错误');
        }
        $allTaxMoney = 0;
        foreach ($res as $k => $v) {
            $allTaxMoney = Utils::processMoney($allTaxMoney, $v['tax_money'], '+', 6);
        }
        $allTaxMoney = round($allTaxMoney, 2);
        $this->sureRes = ['allTaxMoney' => $allTaxMoney, 'json_rate' => $res];
        return $this;
    }

    //获取真正的数据
    public function process() {
        $res = $this->sureRes;
        $data = [];
        if ($this->data['money_type'] == 1) {
            $res['get_money'] = Utils::processMoney($this->data['money'], $res['allTaxMoney'], '-', 3);
            $res['money'] = $this->data['money'];
            $res['ca_money'] = Utils::processMoney($this->data['money'], config('site.money_tax_radio'), '*', 3);
        } else {
            $res['get_money'] = $this->data['money']; //实发
            $res['money'] = Utils::processMoney($this->data['money'], $res['allTaxMoney'], '+', 2);
            $res['ca_money'] = Utils::processMoney($res['money'], config('site.money_tax_radio'), '*', 3);
        }
        $this->sureRes = $res;
        return $res;
    }

    /**
     * 根据应发金额，推算实发金额
     * @param array $oldDetail detail方法测算结果
     * @return array $moneyDetail
     */
    public function taxMoney($oldDetail) {
        //纳税金额 应纳税所得额
        $new = Utils::processMoney($this->data['money'], self:: $radio, '*', 6);
        $moneyDetail = [];
        //由小到大 排好的顺序$all += Utils::processMoney($money, $v['tax_rate'], '*');
        foreach (self::$config as $k => $v) {
            if ($new <= 0) {
                break;
            }
            if ($k < $oldDetail['index']) {
                continue;
            }
            //相等的时候扣除
            if ($k == $oldDetail['index']) { //等于老的比较特殊单独处理
                //大于剩余 或者小于剩余
                if ($new <= $oldDetail['remain']) {
                    $temp = $this->tempArr($new, $v['tax_rate'], $v['kouchushu']);
                    array_push($moneyDetail, $temp);
                    return $moneyDetail;
                } else {
                    if ($oldDetail['remain'] == 0) {continue;};
                    $temp = $this->tempArr($oldDetail['remain'], $v['tax_rate'], $v['kouchushu']);
                    array_push($moneyDetail, $temp);
                    $new = Utils::processMoney($new, $oldDetail['remain'], '-', 6);
                }
            } else {
                if($new <= $v['tax_money']) {
                    $temp = $this->tempArr($new, $v['tax_rate'], $v['kouchushu']);
                    array_push($moneyDetail, $temp);
                    return $moneyDetail;
                } else {
                    $temp = $this->tempArr($v['tax_money'], $v['tax_rate'], $v['kouchushu']);
                    $new = Utils::processMoney($new, $v['tax_money'], '-', 6);
                    array_push($moneyDetail, $temp);
                }
            }
        }

        return $moneyDetail; //要缴纳的税款
    }

    /*
    * 通过实发推导 应发
    * $new 为实发金额  是扣除税的金额
    * $oldDetail 为历史记录
    * */
    public function taxRealMoney($oldDetail) {
        $realRemain = $this->calculateReal($oldDetail['remain'], $oldDetail['config']);  //当前段位实发
        $new = $this->data['money'];  //本次实发金额
        $moneyDetail = [];            //计算数组
        if ($realRemain >= $new) {
            $origin = $this->calculateOrigin($new, $oldDetail['config']);
            array_push($moneyDetail, $origin['detail']);
            return $moneyDetail;
        } else {
            //如果本段剩余 不为0 需要计算
            if ($realRemain > 0) {
                $new = Utils::processMoney($new, $realRemain, '-', 8);  //剩余实发
                $origin = $this->calculateOrigin($realRemain, $oldDetail['config']);  //本段为应发
                array_push($moneyDetail, $origin['detail']);
            }
            foreach (self::$config as $k => $v) {
                if ($k > $oldDetail['index']) {
                    //本段位实发总额
                    $realRemain = $this->calculateReal($v['tax_money'], $v);
                    if ($realRemain >= $new) {
                        $origin = $this->calculateOrigin($new, $v);
                        array_push($moneyDetail, $origin['detail']);
                        break;
                    } else {
                        $origin = $this->calculateOrigin($realRemain, $v);
                        array_push($moneyDetail, $origin['detail']);
                        $new = Utils::processMoney($new, $realRemain, '-', 6);
                    }

                }
            }

            return $moneyDetail;
        }
    }

    /**
     * 组装数据
     */
    protected function tempArr($ca_money, $tax_rate, $kouchushu) {
        $temp['ca_money'] = $ca_money;  //应税所得额 *10%之后金额
        $temp['tax_money'] = Utils::processMoney($ca_money, $tax_rate, '*', 6); //纳税金额
        $temp['tax_rate'] = $tax_rate;  //税率
        $temp['kouchushu'] = $kouchushu; //扣除数

        return $temp;
    }

    /*
     * 通过应税所得额 推到实发金额
     * $orign 这个为应税所得额
     * 计算实发金额 应发*redio  - 纳税金额 = 实发
     * */
    public function calculateReal($origin, $detail) {
        $yingfa = Utils::processMoney($origin, self::$radio, '/',6);
        $tax_money = Utils::processMoney($origin, $detail['tax_rate'], '*',6);  //纳税金额

        return Utils::processMoney($yingfa, $tax_money, '-', 6);
    }

    /*
     * 通过实发金额推到应发金额
     * $real 实发
     * 应发*10% * 税率 = 纳税金额
     * 实发 = 应发 - 纳税金额    应发-应发*10%*税率  = 实发   应发 = 实发/（1-10%*税率）
     * */
    public function calculateOrigin($real, $detail) {
        $temp = Utils::processMoney(self::$radio, $detail['tax_rate'], '*', 8);
        $tax = Utils::processMoney(1, $temp, '-',8);
        $originMoney = Utils::processMoney($real, $tax, '/', 8);

        $ca_money = Utils::processMoney($originMoney, self::$radio, '*', 8);
        $temp = $this->tempArr($ca_money, $detail['tax_rate'], $detail['kouchushu']);

        return [
            'originMoney' => $originMoney,//应发
            'detail' => $temp
        ];
    }


    /**
     * 记录测算细节 测算oldMoney所处等级
     * @return array $maxRate
     */
    public function  detail() {
        $oldMoney = Utils::processMoney($this->old, self::$radio, '*', 6);
        $maxRate = [];
        foreach (self::$config as $k => $v) {
            if($oldMoney <= $v['tax_money']) {
                $maxRate['index'] = $k;  //当前等级索引
                $maxRate['config'] = $v; //
                $maxRate['remain'] = Utils::processMoney($v['tax_money'], $oldMoney, '-', 6);
                return $maxRate;
            } else {
                $oldMoney -= $v['tax_money'];
            }
        }

        return $maxRate;
    }

    private function __clone() {} //声明私有的克隆方法，防止对象被克隆

    public function __sleep() { //重写__sleep方法，将返回置空，防止序列化反序列化获得新的对象
        return [];
    }
}